#include "MyIOCTL.h"
#include <limits.h>

#define HEX(x) std::setw(2) << std::setfill(L'0') << std::hex << (int)(x)

#define printGUID(x) std::hex << x.Data1 << L'-' \
		<< x.Data2 << L'-' \
		<< x.Data3 << L'-' \
		<< std::setw(2) << std::setfill(L'0') \
		<< (bool)(x.Data4[0]) \
		<< (bool)(x.Data4[1]) << L'-' \
		<< (bool)(x.Data4[2]) \
		<< (bool)(x.Data4[3]) \
		<< (bool)(x.Data4[4]) \
		<< (bool)(x.Data4[5]) \
		<< (bool)(x.Data4[6]) \
		<< (bool)(x.Data4[7]) \


#define printCapFlags(x) L"<tr><td>HubIsHighSpeedCapable</td><td>" \
	 << (bool)(x.HubIsHighSpeedCapable & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsHighSpeed</td><td>" \
	 << (bool)(x.HubIsHighSpeed & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsMultiTtCapable</td><td>" \
	 << (bool)(x.HubIsMultiTtCapable & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsMultiTt</td><td>" \
	 << (bool)(x.HubIsMultiTt & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsRoot</td><td>" \
	 << (bool)(x.HubIsRoot & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsArmedWakeOnConnect</td><td>" \
	 << (bool)(x.HubIsArmedWakeOnConnect & ULONG_MAX) << L"</td><tr>" \
	 << L"<tr><td>HubIsBusPowered</td><td>" \
	 << (bool)(x.HubIsBusPowered & ULONG_MAX) << L"</td><tr>" \

extern const char *PacketNames[];

void MY_IOCTL_EMPTY::DeserializeEmpty(void *pBuffer, long bufSize, unsigned char packType)
{
	buffer.SetBuffer(pBuffer, bufSize);
	packetName = PacketNames[packType];
	buffer.Read(&isCompleted, sizeof(isCompleted));
	if (isCompleted)
	{
        buffer.Read(&status, sizeof(status));
        direction = "UP";
	}
    else
        direction = "DOWN";
}

std::wstring MY_IOCTL_EMPTY::GetDetailedInfo()
{
	return std::wstring(L"This IOCTL has no associated data");
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_BUS_INFO::GetDetailedInfo()
{
	std::wstringstream tmp;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<tr><td><b>TotalBandwidth:</b></td><td>"       << TotalBandwidth       << L"</td></tr>";
	tmp << L"<tr><td><b>ConsumedBandwidth:</b></td><td>"    << ConsumedBandwidth    << L"</td></tr>";
	tmp << L"<tr><td><b>ControllerNameLength:</b></td><td>" << ControllerNameLength << L"</td></tr>";
	return tmp.str();	
}

void MY_IOCTL_INTERNAL_USB_GET_BUS_INFO::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&TotalBandwidth,       sizeof(TotalBandwidth));
		buffer.Read(&ConsumedBandwidth,    sizeof(ConsumedBandwidth));
		buffer.Read(&ControllerNameLength, sizeof(ControllerNameLength));
	}
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned i;
	wchar_t *s = HubName.get();
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<tr><td><b>ActualLength:</b></td><td>"  << ActualLength << L"</td></tr>"; 
	tmp << L"<tr><td><b>HubName:</b></td><td>";
	for (i=0; i<(ActualLength-sizeof(long))/2; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";
	return tmp.str();
}

void MY_IOCTL_INTERNAL_USB_GET_CONTROLLER_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&ActualLength, sizeof(ActualLength));

	HubName = std::auto_ptr<wchar_t>(new wchar_t[(ActualLength-sizeof(long))/2]);
	wchar_t *pHubName = HubName.get();
	for (i=0; i<(ActualLength-sizeof(long))/2; ++i)
	{
		buffer.Read(&pHubName[i],  sizeof(wchar_t));
	}
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_HUB_NAME::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned i;
	wchar_t *s = HubName.get();
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<tr><td><b>ActualLength:</b></td><td>"  << ActualLength << L"</td></tr>"; 
	tmp << L"<tr><td><b>HubName:</b></td><td>";
	for (i=0; i<(ActualLength-sizeof(long))/2; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";
	return tmp.str();
}

void MY_IOCTL_INTERNAL_USB_GET_HUB_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&ActualLength, sizeof(ActualLength));

	HubName = std::auto_ptr<wchar_t>(new wchar_t[(ActualLength-sizeof(long))/2]);
	wchar_t *pHubName = HubName.get();
	for (i=0; i<(ActualLength-sizeof(long))/2; ++i)
	{
		buffer.Read(&pHubName[i],  sizeof(wchar_t));
	}	
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_PORT_STATUS::GetDetailedInfo()
{
	std::wstringstream tmp;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<b>portStatusFlags:</b><br>";

	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;USBD_PORT_ENABLED :</td><td>"
		<< (bool)(portStatusFlags & 0x1) << L"</td></tr>";
	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;USBD_PORT_CONNECTED :</td><td>"
		<< (bool)(portStatusFlags & 0x2) << L"</td></tr>";
	
	return tmp.str();
}

void MY_IOCTL_INTERNAL_USB_GET_PORT_STATUS::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&portStatusFlags, sizeof(portStatusFlags));
	}
}

std::wstring MY_IOCTL_USB_GET_HUB_CAPABILITIES::GetDetailedInfo()
{
	std::wstringstream tmp;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<tr><td><b>HubIs2xCapable:</b></td><td>" << HubIs2xCapable << L"</td></tr>";

	return tmp.str();
}

void MY_IOCTL_USB_GET_HUB_CAPABILITIES::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&HubIs2xCapable, sizeof(HubIs2xCapable));
	}
}

std::wstring MY_IOCTL_USB_GET_HUB_CAPABILITIES_EX::GetDetailedInfo()
{
	std::wstringstream tmp;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<b>HubFlags:</b><br>" << printCapFlags(HubFlags);

	return tmp.str();
}

void MY_IOCTL_USB_GET_HUB_CAPABILITIES_EX::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (isCompleted)
	{
		buffer.Read(&HubFlags.ul, sizeof(HubFlags.ul));
	}
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned i;
	wchar_t *s;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");
	
	tmp << L"<tr><td><b>Version:</b></td><td>" << Version << L"</td></tr>";
	tmp << L"<tr><td><b>Length:</b></td><td>"  << Length << L"</td></tr>";
	tmp << L"<b>HubFlags:</b><br>" << printCapFlags(HubFlags);
	tmp << L"<tr><td><b>HardwareIds:</b></td><td>";	

	s = HardwareIds.get();
	for (i=0; i<HardwareIdsLen; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";

	s = CompatibleIds.get();
	for (i=0; i<CompatibleIdsLen; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";

	s = DeviceDescription.get();
	for (i=0; i<DeviceDescriptionLen; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";
	tmp << L"<b>UxdSettings:</b><br>";
	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;Version:</td><td>" << Version << L"</td></tr>";


	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;PnpGuid:</td><td>" << printGUID(UxdSettings.PnpGuid) << L"</td></tr>";
	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;PnpGuid:</td><td>" << printGUID(UxdSettings.OwnerGuid) << L"</td></tr>";

	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;DeleteOnShutdown:</td><td>"
		<< UxdSettings.DeleteOnShutdown << L"</td></tr>";
	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;DeleteOnReload:</td><td>"
		<< UxdSettings.DeleteOnReload << L"</td></tr>";
	tmp << L"<tr><td>&nbsp;&nbsp;&nbsp;DeleteOnDisconnect:</td><td>"
		<< UxdSettings.DeleteOnDisconnect << L"</td></tr>";

	return tmp.str();
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::DeserializeUsbIdString(std::auto_ptr<wchar_t> &pStr, unsigned &strLen)
{
	unsigned long LengthInBytes, i, strLength;
	buffer.Read(&LengthInBytes, sizeof(LengthInBytes));
	
	strLen = LengthInBytes/sizeof(wchar_t);
	pStr = std::auto_ptr<wchar_t>(new wchar_t[strLength]);
	wchar_t *pwStr = pStr.get();
	for (i=0; i<strLen; ++i)
	{
		buffer.Read(&pwStr[i], sizeof(wchar_t));
	}
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::DeserializeGUID(MY_GUID &guid)
{
	buffer.Read(&guid.Data1, sizeof(guid.Data1));
	buffer.Read(&guid.Data2, sizeof(guid.Data2));
	buffer.Read(&guid.Data3, sizeof(guid.Data3));
	buffer.Read( guid.Data4, sizeof(guid.Data4));
}

void MY_IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}

	buffer.Read(&Version,     sizeof(Version));
	buffer.Read(&Length,      sizeof(Length));
	buffer.Read(&HubFlags.ul, sizeof(HubFlags.ul));

	DeserializeUsbIdString(HardwareIds, HardwareIdsLen);
	DeserializeUsbIdString(CompatibleIds, CompatibleIdsLen);
	DeserializeUsbIdString(DeviceDescription, DeviceDescriptionLen);

	buffer.Read(&UxdSettings.Version, sizeof(UxdSettings.Version));

	DeserializeGUID(UxdSettings.PnpGuid);
	DeserializeGUID(UxdSettings.OwnerGuid);

	buffer.Read(&UxdSettings.DeleteOnShutdown,   sizeof(UxdSettings.DeleteOnShutdown));
	buffer.Read(&UxdSettings.DeleteOnReload,     sizeof(UxdSettings.DeleteOnReload));
	buffer.Read(&UxdSettings.DeleteOnDisconnect, sizeof(UxdSettings.DeleteOnDisconnect));
}

std::wstring MY_IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned i;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");

	tmp << L"<tr><td><b>PciBusNumber:</b></td><td>"      << PciBusNumber      << L"</td></tr>";
	tmp << L"<tr><td><b>PciDeviceNumber:</b></td><td>"   << PciDeviceNumber   << L"</td></tr>";
	tmp << L"<tr><td><b>PciFunctionNumber:</b></td><td>" << PciFunctionNumber << L"</td></tr>";
	tmp << L"<tr><td><b>RootHubPortNumber:</b></td><td>" << RootHubPortNumber << L"</td></tr><br>";	

	for (i=0; i<5; ++i)
	{
		tmp << L"<tr><td>HubPortNumber["<<i<<"]:</td><td>" << HubPortNumber[i] << L"</td></tr>";
	}
	return tmp.str();
}

void MY_IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{
		return;
	}
	buffer.Read(&PciBusNumber,      sizeof(PciBusNumber));
	buffer.Read(&PciDeviceNumber,   sizeof(PciDeviceNumber));
	buffer.Read(&PciFunctionNumber, sizeof(PciFunctionNumber));
	buffer.Read(&RootHubPortNumber, sizeof(RootHubPortNumber));
	buffer.Read( HubPortNumber,     sizeof(HubPortNumber));
}

std::wstring MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned long i;
	tmp << L"<tr><td><b>ConnectionIndex:</b></td><td>"  << ConnectionIndex << L"</td></tr>";
	if (!isCompleted)
		return tmp.str();

	tmp << L"<b>ConnectionIndex:</b><br>";

	tmp << L"<tr><td>bLength:</td><td>"           << DeviceDescriptor.bLength << L"</td></tr>";
	tmp << L"<tr><td>bDescriptorType:</td><td>"   << DeviceDescriptor.bDescriptorType << L"</td></tr>";
	tmp << L"<tr><td>bcdUSB:</td><td>"            << DeviceDescriptor.bcdUSB << L"</td></tr>";
	tmp << L"<tr><td>bDeviceClass:</td><td>"      << DeviceDescriptor.bDeviceClass << L"</td></tr>";
	tmp << L"<tr><td>bDeviceSubClass:</td><td>"   << DeviceDescriptor.bDeviceSubClass << L"</td></tr>";
	tmp << L"<tr><td>bDeviceProtocol:</td><td>"   << DeviceDescriptor.bDeviceProtocol << L"</td></tr>";
	tmp << L"<tr><td>bMaxPacketSize0:</td><td>"   << DeviceDescriptor.bMaxPacketSize0 << L"</td></tr>";
	tmp << L"<tr><td>idVendor:</td><td>"          << DeviceDescriptor.idVendor << L"</td></tr>";
	tmp << L"<tr><td>idProduct:</td><td>"         << DeviceDescriptor.idProduct << L"</td></tr>";
	tmp << L"<tr><td>bcdDevice:</td><td>"         << DeviceDescriptor.bcdDevice << L"</td></tr>";
	tmp << L"<tr><td>iManufacturer:</td><td>"     << DeviceDescriptor.iManufacturer << L"</td></tr>";
	tmp << L"<tr><td>iProduct:</td><td>"          << DeviceDescriptor.iProduct << L"</td></tr>";
	tmp << L"<tr><td>iSerialNumber:</td><td>"     << DeviceDescriptor.iSerialNumber << L"</td></tr>";
	tmp << L"<tr><td>bNumConfigurations:</td><td>"<< DeviceDescriptor.bNumConfigurations << L"</td></tr><br>";


	tmp << L"<tr><td><b>CurrentConfigurationValue:</b></td><td>0x"
		<< HEX(CurrentConfigurationValue) << L"</td></tr>";

	tmp << L"<tr><td><b>LowSpeed:</b></td><td>"          << LowSpeed << L"</td></tr>";
	tmp << L"<tr><td><b>DeviceIsHub:</b></td><td>"       << DeviceIsHub << L"</td></tr>";
	tmp << L"<tr><td><b>DeviceAddress:</b></td><td>"     << DeviceAddress << L"</td></tr>";
	tmp << L"<tr><td><b>NumberOfOpenPipes:</b></td><td>" << NumberOfOpenPipes << L"</td></tr>";
	tmp << L"<tr><td><b>ConnectionStatus:</b></td><td>"  << ConnectionStatus << L"</td></tr>";

	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		tmp << L"<b>PipeList["<<i<<"]</b>.EndpointDescriptor:<br>";
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;

		
		tmp << L"<tr><td>bLength:</td><td>"           << pED->bLength << L"</td></tr>";
		tmp << L"<tr><td>bDescriptorType:</td><td>"   << pED->bDescriptorType << L"</td></tr>";
		tmp << L"<tr><td>bEndpointAddress:</td><td>"            << pED->bEndpointAddress << L"</td></tr>";
		tmp << L"<tr><td>bmAttributes:</td><td>"      << pED->bmAttributes << L"</td></tr>";
		tmp << L"<tr><td>wMaxPacketSize:</td><td>"   << pED->wMaxPacketSize << L"</td></tr>";
		tmp << L"<tr><td>bInterval:</td><td>"   << pED->bInterval << L"</td></tr><br>";

		tmp << L"<tr><td><b>PipeList["<<i<<"]</b>.ScheduleOffset:</td><td>"
			<< pPipeList[i].ScheduleOffset << L"</td></tr>";
	}
	return tmp.str();
}

void MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}	

	buffer.Read(&DeviceDescriptor.bLength,            sizeof(DeviceDescriptor.bLength));
	buffer.Read(&DeviceDescriptor.bDescriptorType,    sizeof(DeviceDescriptor.bDescriptorType));
	buffer.Read(&DeviceDescriptor.bcdUSB,             sizeof(DeviceDescriptor.bcdUSB));
	buffer.Read(&DeviceDescriptor.bDeviceClass,       sizeof(DeviceDescriptor.bDeviceClass));
	buffer.Read(&DeviceDescriptor.bDeviceSubClass,    sizeof(DeviceDescriptor.bDeviceSubClass));
	buffer.Read(&DeviceDescriptor.bDeviceProtocol,    sizeof(DeviceDescriptor.bDeviceProtocol));
	buffer.Read(&DeviceDescriptor.bMaxPacketSize0,    sizeof(DeviceDescriptor.bMaxPacketSize0));
	buffer.Read(&DeviceDescriptor.idVendor,           sizeof(DeviceDescriptor.idVendor));
	buffer.Read(&DeviceDescriptor.idProduct,          sizeof(DeviceDescriptor.idProduct));
	buffer.Read(&DeviceDescriptor.bcdDevice,          sizeof(DeviceDescriptor.bcdDevice));
	buffer.Read(&DeviceDescriptor.iManufacturer,      sizeof(DeviceDescriptor.iManufacturer));
	buffer.Read(&DeviceDescriptor.iProduct,           sizeof(DeviceDescriptor.iProduct));
	buffer.Read(&DeviceDescriptor.iSerialNumber,      sizeof(DeviceDescriptor.iSerialNumber));
	buffer.Read(&DeviceDescriptor.bNumConfigurations, sizeof(DeviceDescriptor.bNumConfigurations));

	buffer.Read(&CurrentConfigurationValue, sizeof(CurrentConfigurationValue));
	////
	buffer.Read(&LowSpeed,                  sizeof(LowSpeed));
	////
	buffer.Read(&DeviceIsHub,               sizeof(DeviceIsHub));
	buffer.Read(&DeviceAddress,             sizeof(DeviceAddress));
	buffer.Read(&NumberOfOpenPipes,         sizeof(NumberOfOpenPipes));
	buffer.Read(&ConnectionStatus,          sizeof(ConnectionStatus));

	PipeList = std::auto_ptr<MY_USB_PIPE_INFO>(new MY_USB_PIPE_INFO[NumberOfOpenPipes]);
	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;
		buffer.Read(&pED->bLength,          sizeof(pED->bLength));
		buffer.Read(&pED->bDescriptorType,  sizeof(pED->bDescriptorType));
		buffer.Read(&pED->bEndpointAddress, sizeof(pED->bEndpointAddress));
		buffer.Read(&pED->bmAttributes,     sizeof(pED->bmAttributes));
		buffer.Read(&pED->wMaxPacketSize,   sizeof(pED->wMaxPacketSize));
		buffer.Read(&pED->bInterval,        sizeof(pED->bInterval));

		buffer.Read(&pPipeList[i].ScheduleOffset, sizeof(pPipeList[i].ScheduleOffset));
	}
}

// This function is identical to the previous one except one line
// TODO: fix this
void MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}	

	buffer.Read(&DeviceDescriptor.bLength,            sizeof(DeviceDescriptor.bLength));
	buffer.Read(&DeviceDescriptor.bDescriptorType,    sizeof(DeviceDescriptor.bDescriptorType));
	buffer.Read(&DeviceDescriptor.bcdUSB,             sizeof(DeviceDescriptor.bcdUSB));
	buffer.Read(&DeviceDescriptor.bDeviceClass,       sizeof(DeviceDescriptor.bDeviceClass));
	buffer.Read(&DeviceDescriptor.bDeviceSubClass,    sizeof(DeviceDescriptor.bDeviceSubClass));
	buffer.Read(&DeviceDescriptor.bDeviceProtocol,    sizeof(DeviceDescriptor.bDeviceProtocol));
	buffer.Read(&DeviceDescriptor.bMaxPacketSize0,    sizeof(DeviceDescriptor.bMaxPacketSize0));
	buffer.Read(&DeviceDescriptor.idVendor,           sizeof(DeviceDescriptor.idVendor));
	buffer.Read(&DeviceDescriptor.idProduct,          sizeof(DeviceDescriptor.idProduct));
	buffer.Read(&DeviceDescriptor.bcdDevice,          sizeof(DeviceDescriptor.bcdDevice));
	buffer.Read(&DeviceDescriptor.iManufacturer,      sizeof(DeviceDescriptor.iManufacturer));
	buffer.Read(&DeviceDescriptor.iProduct,           sizeof(DeviceDescriptor.iProduct));
	buffer.Read(&DeviceDescriptor.iSerialNumber,      sizeof(DeviceDescriptor.iSerialNumber));
	buffer.Read(&DeviceDescriptor.bNumConfigurations, sizeof(DeviceDescriptor.bNumConfigurations));

	buffer.Read(&CurrentConfigurationValue, sizeof(CurrentConfigurationValue));
	////
	buffer.Read(&Speed,                     sizeof(Speed));
	////
	buffer.Read(&DeviceIsHub,               sizeof(DeviceIsHub));
	buffer.Read(&DeviceAddress,             sizeof(DeviceAddress));
	buffer.Read(&NumberOfOpenPipes,         sizeof(NumberOfOpenPipes));
	buffer.Read(&ConnectionStatus,          sizeof(ConnectionStatus));

	PipeList = std::auto_ptr<MY_USB_PIPE_INFO>(new MY_USB_PIPE_INFO[NumberOfOpenPipes]);
	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;
		buffer.Read(&pED->bLength,          sizeof(pED->bLength));
		buffer.Read(&pED->bDescriptorType,  sizeof(pED->bDescriptorType));
		buffer.Read(&pED->bEndpointAddress, sizeof(pED->bEndpointAddress));
		buffer.Read(&pED->bmAttributes,     sizeof(pED->bmAttributes));
		buffer.Read(&pED->wMaxPacketSize,   sizeof(pED->wMaxPacketSize));
		buffer.Read(&pED->bInterval,        sizeof(pED->bInterval));

		buffer.Read(&pPipeList[i].ScheduleOffset, sizeof(pPipeList[i].ScheduleOffset));
	}
}

std::wstring MY_IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned long i;
	tmp << L"<tr><td><b>ConnectionIndex:</b></td><td>"  << ConnectionIndex << L"</td></tr>";
	if (!isCompleted)
		return tmp.str();

	tmp << L"<b>ConnectionIndex:</b><br>";

	tmp << L"<tr><td>bLength:</td><td>"           << DeviceDescriptor.bLength << L"</td></tr>";
	tmp << L"<tr><td>bDescriptorType:</td><td>"   << DeviceDescriptor.bDescriptorType << L"</td></tr>";
	tmp << L"<tr><td>bcdUSB:</td><td>"            << DeviceDescriptor.bcdUSB << L"</td></tr>";
	tmp << L"<tr><td>bDeviceClass:</td><td>"      << DeviceDescriptor.bDeviceClass << L"</td></tr>";
	tmp << L"<tr><td>bDeviceSubClass:</td><td>"   << DeviceDescriptor.bDeviceSubClass << L"</td></tr>";
	tmp << L"<tr><td>bDeviceProtocol:</td><td>"   << DeviceDescriptor.bDeviceProtocol << L"</td></tr>";
	tmp << L"<tr><td>bMaxPacketSize0:</td><td>"   << DeviceDescriptor.bMaxPacketSize0 << L"</td></tr>";
	tmp << L"<tr><td>idVendor:</td><td>"          << DeviceDescriptor.idVendor << L"</td></tr>";
	tmp << L"<tr><td>idProduct:</td><td>"         << DeviceDescriptor.idProduct << L"</td></tr>";
	tmp << L"<tr><td>bcdDevice:</td><td>"         << DeviceDescriptor.bcdDevice << L"</td></tr>";
	tmp << L"<tr><td>iManufacturer:</td><td>"     << DeviceDescriptor.iManufacturer << L"</td></tr>";
	tmp << L"<tr><td>iProduct:</td><td>"          << DeviceDescriptor.iProduct << L"</td></tr>";
	tmp << L"<tr><td>iSerialNumber:</td><td>"     << DeviceDescriptor.iSerialNumber << L"</td></tr>";
	tmp << L"<tr><td>bNumConfigurations:</td><td>"<< DeviceDescriptor.bNumConfigurations << L"</td></tr><br>";


	tmp << L"<tr><td><b>CurrentConfigurationValue:</b></td><td>0x"
		<< HEX(CurrentConfigurationValue) << L"</td></tr>";

	static const char *speeds[] =
	{
		"UsbLowSpeed",
		"UsbFullSpeed",
		"UsbHighSpeed"
	};
	tmp << L"<tr><td><b>Speed:</b></td><td>" << speeds[Speed] << L"</td></tr>";

	tmp << L"<tr><td><b>DeviceIsHub:</b></td><td>"       << DeviceIsHub << L"</td></tr>";
	tmp << L"<tr><td><b>DeviceAddress:</b></td><td>"     << DeviceAddress << L"</td></tr>";
	tmp << L"<tr><td><b>NumberOfOpenPipes:</b></td><td>" << NumberOfOpenPipes << L"</td></tr>";
	tmp << L"<tr><td><b>ConnectionStatus:</b></td><td>"  << ConnectionStatus << L"</td></tr>";

	MY_USB_PIPE_INFO *pPipeList = PipeList.get();
	for (i=0; i<NumberOfOpenPipes; ++i)
	{
		tmp << L"<b>PipeList["<<i<<"]</b>.EndpointDescriptor:<br>";
		MY_USB_ENDPOINT_DESCRIPTOR *pED = (MY_USB_ENDPOINT_DESCRIPTOR *) &pPipeList[i].EndpointDescriptor;

		
		tmp << L"<tr><td>bLength:</td><td>"           << pED->bLength << L"</td></tr>";
		tmp << L"<tr><td>bDescriptorType:</td><td>"   << pED->bDescriptorType << L"</td></tr>";
		tmp << L"<tr><td>bEndpointAddress:</td><td>"  << pED->bEndpointAddress << L"</td></tr>";
		tmp << L"<tr><td>bmAttributes:</td><td>"      << pED->bmAttributes << L"</td></tr>";
		tmp << L"<tr><td>wMaxPacketSize:</td><td>"    << pED->wMaxPacketSize << L"</td></tr>";
		tmp << L"<tr><td>bInterval:</td><td>"         << pED->bInterval << L"</td></tr><br>";

		tmp << L"<tr><td><b>PipeList["<<i<<"]</b>.ScheduleOffset:</td><td>"
			<< pPipeList[i].ScheduleOffset << L"</td></tr>";
	}
	return tmp.str();
}

std::wstring MY_IOCTL_USB_GET_NODE_CONNECTION_NAME::GetDetailedInfo()
{
	std::wstringstream tmp;
	unsigned i;
	wchar_t *s = NodeName.get();
	tmp << L"<tr><td><b>ConnectionIndex:</b></td><td>"  << ConnectionIndex << L"</td></tr>"; 
	if (!isCompleted)
		return tmp.str();

	tmp << L"<tr><td><b>ActualLength:</b></td><td>"  << ActualLength << L"</td></tr>"; 
	tmp << L"<tr><td><b>NodeName:</b></td><td>";
	for (i=0; i<ActualLength/2; ++i)
	{
		tmp << s[i];
	}
	tmp << L"</td></tr>";
	return tmp.str();
}

void MY_IOCTL_USB_GET_NODE_CONNECTION_NAME::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	unsigned long i;
	DeserializeEmpty(pBuffer, bufSize, packType);
	buffer.Read(&ConnectionIndex, sizeof(ConnectionIndex));
	if (!isCompleted)
	{				
		return;
	}

	buffer.Read(&ActualLength, sizeof(ActualLength));

	NodeName = std::auto_ptr<wchar_t>(new wchar_t[ActualLength/2]);
	wchar_t *pNodeName = NodeName.get();
	for (i=0; i<ActualLength/2; ++i)
	{
		buffer.Read(&pNodeName[i],  sizeof(wchar_t));
	}
}

std::wstring MY_IOCTL_USB_GET_NODE_INFORMATION::GetDetailedInfo()
{
	std::wstringstream tmp;
	if (!isCompleted)
		return std::wstring(L"No data on the way down");
	
	if (NodeType == UsbMIParent)
	{
		tmp << L"<tr><td><b>NodeType:</b></td><td> UsbMIParent</td></tr><br>"; 
		tmp << L"<tr><td><b>NumberOfInterfaces:</b></td><td>" << u.NumberOfInterfaces << L"</td></tr>";
		return tmp.str();
	}

	tmp << L"<tr><td><b>NodeType:</b></td><td> UsbHub</td></tr><br>";
	tmp << L"<b>HubDescriptor:</b><br>";

	MY_USB_HUB_DESCRIPTOR *pHubDesc = &((MY_USB_HUB_INFORMATION *) &u)->HubDescriptor;
	tmp << L"<tr><td><b>bDescriptorLength:</b></td><td>0x"   << HEX(pHubDesc->bDescriptorLength) << L"</td></tr>";
	tmp << L"<tr><td><b>bDescriptorType:</b></td><td>0x"     << HEX(pHubDesc->bDescriptorType) << L"</td></tr>";
	tmp << L"<tr><td><b>bNumberOfPorts:</b></td><td>0x"      << HEX(pHubDesc->bNumberOfPorts) << L"</td></tr>";
	tmp << L"<tr><td><b>wHubCharacteristics:</b></td><td>0x" <<     pHubDesc->wHubCharacteristics << L"</td></tr>";
	tmp << L"<tr><td><b>bPowerOnToPowerGood:</b></td><td>0x" << HEX(pHubDesc->bPowerOnToPowerGood) << L"</td></tr>";
	tmp << L"<tr><td><b>bHubControlCurrent:</b></td><td>0x"  << HEX(pHubDesc->bHubControlCurrent) << L"</td></tr>";

	tmp << L"<tr><td><b>HubIsBusPowered:</b></td><td>"  << (bool)((MY_USB_HUB_INFORMATION *) &u)->HubIsBusPowered << L"</td></tr>";

	return tmp.str();
}

void MY_IOCTL_USB_GET_NODE_INFORMATION::Deserialize(void *pBuffer, long bufSize, unsigned char packType)
{
	DeserializeEmpty(pBuffer, bufSize, packType);
	if (!isCompleted)
	{				
		return;
	}

	buffer.Read(&NodeType, sizeof(NodeType));
	if (NodeType == UsbMIParent)
	{
		buffer.Read(&u.NumberOfInterfaces, sizeof(u.NumberOfInterfaces));
		return;
	}

	MY_USB_HUB_DESCRIPTOR *pHubDesc = &((MY_USB_HUB_INFORMATION *) &u)->HubDescriptor;

	buffer.Read(&pHubDesc->bDescriptorLength,   sizeof(pHubDesc->bDescriptorLength));
	buffer.Read(&pHubDesc->bDescriptorType,     sizeof(pHubDesc->bDescriptorType));
	buffer.Read(&pHubDesc->bNumberOfPorts,      sizeof(pHubDesc->bNumberOfPorts));
	buffer.Read(&pHubDesc->wHubCharacteristics, sizeof(pHubDesc->wHubCharacteristics));
	buffer.Read(&pHubDesc->bPowerOnToPowerGood, sizeof(pHubDesc->bPowerOnToPowerGood));
	buffer.Read(&pHubDesc->bHubControlCurrent,  sizeof(pHubDesc->bHubControlCurrent));

    buffer.Read(&((MY_USB_HUB_INFORMATION *) &u)->HubIsBusPowered, sizeof(bool));
}
